# -*- coding: utf-8 -*-

import os
import re
import time
import urllib

from flask import jsonify, Blueprint, request, current_app
from flasgger import swag_from
from werkzeug.utils import secure_filename
from ..utils import make_response
from ..config import Config
from PIL import Image  # 用于检测是否为图片文件
import io
from openpyxl import load_workbook  # 用于处理 Excel 文件

bp = Blueprint('uploadfile', __name__)

UPLOAD_ROOT = Config.resource_local_path

def clean_filename(filename):
    """
    清理文件名，移除非法字符和括号内的数字，仅保留字母、数字、点、下划线、破折号和空格。
    """
    filename = urllib.parse.unquote(filename)
    filename = re.sub(r'\(\d+\)', '', filename)  # 去除括号及括号内的数字
    filename = re.sub(r'[^\w.\-_ ]', '', filename)  # 移除非法字符
    filename = filename.strip()  # 去除文件名开头或结尾的多余空格
    return filename

def generate_timestamped_filename(filename):
    """生成带有时间戳的文件名"""
    name, ext = os.path.splitext(filename)
    timestamp = time.strftime("%Y%m%d%H%M%S")
    return f"{name}-{timestamp}{ext}"

@bp.route('/uploadfile', methods=['POST'])
@swag_from({
    'parameters': [
        {
            'name': 'directory_name',
            'in': 'formData',
            'type': 'string',
            'required': False,
            'description': '目录名称（可选）'
        },
        {
            'name': 'user_id',
            'in': 'formData',
            'type': 'string',
            'required': True,
            'description': '创建目录用户ID'
        },
        {
            'name': 'file',
            'in': 'formData',
            'type': 'file',
            'required': True,
            'description': '要上传的文件'
        }
    ],
    'responses': {
        200: {
            'description': '文件上传成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'message': {'type': 'string'},
                    'file_id': {'type': 'string'}
                }
            }
        }
    }
})
def upload_file():
    """
    文件上传接口，支持版本控制和元数据存储 临时文件上传接口
    ---
    tags:
      - 知识库相关接口
    """
    directory_name = request.form.get('directory_name')
    user_id = request.form.get('user_id')
    file = request.files.get('file')

    if not user_id or not file:
        return make_response(message="缺少必要的表单字段", status=400)

    if file.filename == '':
        return make_response(message="未选择文件", status=400)

    clean_name = clean_filename(file.filename)

    # 检查文件完整性，避免损坏文件
    try:
        file.seek(0)  # 重新定位文件指针
        # 如果是图片，检查其完整性
        if clean_name.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff')):
            Image.open(io.BytesIO(file.read())).verify()  # 验证图片文件
            is_image = True
        else:
            # 对非图片文件简单读取部分内容，确认其可读性
            file.read(512)  # 读取前512字节以验证文件完整性
            is_image = False
    except (IOError, SyntaxError, OSError) as e:
        return make_response(message=f"文件无法读取或损坏: {str(e)}", status=400)
    finally:
        file.seek(0)  # 无论如何，恢复文件指针位置

    # 如果没有提供目录名称，使用文件名作为目录名称
    if not directory_name:
        directory_name = os.path.splitext(clean_name)[0] if is_image else clean_name
        print(f"目录名称为空，使用文件名作为目录名称：{directory_name}")

    # 清理并确保目录名称是安全的
    safe_directory_name = clean_filename(directory_name)

    # 构建目录路径
    final_dir = os.path.join(UPLOAD_ROOT, safe_directory_name)
    os.makedirs(final_dir, exist_ok=True)  # 创建目录（如果不存在）

    # 检查目录下是否已有文件，若有，生成带时间戳的文件名
    file_path = os.path.join(final_dir, clean_name)
    if os.path.exists(file_path):
        clean_name = generate_timestamped_filename(clean_name)
        file_path = os.path.join(final_dir, clean_name)

    # 保存文件到相应的目录
    file.save(file_path)

    # 保存文件信息到 MongoDB
    db = current_app.db
    file_info = {
        "directory_name": safe_directory_name,
        "user_id": user_id,
        "file_name": clean_name,
        "file_path": file_path,
        "final_version": False,
        "uploader_id": user_id,
        "timestamp": time.time(),
        "remark": "图片文件" if is_image else safe_directory_name
    }
    result = db.files.insert_one(file_info)

    return make_response(message=f"文件 {clean_name} 上传成功并保存到 {final_dir}",
                         data={"file_id": str(result.inserted_id)}, status=200)

@bp.route('/upload_approval_excel', methods=['POST'])
@swag_from({
    'parameters': [
        {
            'name': 'user_id',
            'in': 'formData',
            'type': 'string',
            'required': True,
            'description': '创建目录用户ID'
        },
        {
            'name': 'file',
            'in': 'formData',
            'type': 'file',
            'required': True,
            'description': '要上传的 Excel 文件'
        }
    ],
    'responses': {
        200: {
            'description': 'Excel 文件上传成功并解析',
            'schema': {
                'type': 'object',
                'properties': {
                    'message': {'type': 'string'},
                    'file_id': {'type': 'list'},
                }
            },
            'examples': {
                'application/json': {
                  "data": {
                    "file_id": [
                      "66d6eeefae01d4d47dc22f05",
                      "66d6eeefae01d4d47dc22f06",
                      "66d6eeefae01d4d47dc22f07",
                      "66d6eeefae01d4d47dc22f08",
                      "66d6eeefae01d4d47dc22f09"
                    ]
                  },
                  "message": "文件 用户真实姓名.xlsx 上传成功并已解析，审批流程信息已保存",
                  "status": 200
                }
            }
        }
    }
})
def upload_approval_excel():
    """
    专用接口：上传特定格式的 Excel 文件并存储审批流程信息到 MongoDB
    ---
    tags:
      - 审批流程相关接口
    """
    user_id = request.form.get('user_id')
    file = request.files.get('file')

    if not user_id or not file:
        return make_response(message="缺少必要的表单字段", status=400)

    if file.filename == '':
        return make_response(message="未选择文件", status=400)

    clean_name = clean_filename(file.filename)

    # 检查文件扩展名是否为 .xlsx（Excel 文件）
    if not clean_name.lower().endswith('.xlsx'):
        return make_response(message="仅支持上传 .xlsx 格式的 Excel 文件", status=400)

    # 保存文件到临时目录
    temp_dir = os.path.join(Config.PROCESS_PATH, 'temp_excel_uploads')
    os.makedirs(temp_dir, exist_ok=True)
    file_path = os.path.join(temp_dir, clean_name)
    file.save(file_path)

    # 解析 Excel 文件内容
    try:
        # 检查文件是否可读取
        wb = load_workbook(file_path, read_only=True)
        sheet = wb.active

        approval_process = []
        for row in sheet.iter_rows(min_row=2, values_only=True):  # 假设第一行为标题行
            if not row[0] or not row[1]:  # 如果必要字段为空，继续到下一行
                continue
            node_info = {
                "user_real_name": row[0],  # 假设第一列是用户真实姓名
                "approval_node": row[1],   # 假设第二列是审批节点
                "previous_node": row[2] if len(row) > 2 else None  # 假设第三列是上一审批节点
            }
            approval_process.append(node_info)

        # 存储审批流程信息到 MongoDB 的 approvals 集合（表格）
        db = current_app.db
        result = db.approvals.insert_many(approval_process)

    except Exception as e:
        return make_response(message=f"Excel 文件解析失败: {str(e)}。请检查文件格式是否正确或重新上传", status=500)

    return make_response(
        message=f"文件 {clean_name} 上传成功并已解析，审批流程信息已保存",
        data={"file_id": [str(id) for id in result.inserted_ids]},  # 返回插入的文档 ID 列表
        status=200
    )
@bp.route('/get_approval_process', methods=['GET'])
@swag_from({
    'parameters': [
        {
            'name': 'user_real_name',
            'in': 'query',
            'type': 'string',
            'required': True,
            'description': '用户的实名名称'
        },
        {
            'name': 'approval_node',
            'in': 'query',
            'type': 'string',
            'required': True,
            'description': '审批节点'
        }
    ],
    'responses': {
        200: {
            'description': '审批流程信息获取成功',
            'schema': {
                'type': 'object',
                'properties': {
                    'message': {'type': 'string'},
                    'data': {
                        'type': 'array',
                        'items': {
                            'type': 'object',
                            'properties': {
                                'user_real_name': {'type': 'string'},
                                'approval_node': {'type': 'string'},
                                'previous_node': {'type': 'string'},
                                'next_node': {'type': 'string'},
                                'approvers': {'type': 'array', 'items': {'type': 'string'}}
                            }
                        }
                    },
                    'status': {'type': 'integer'}
                }
            },
            'examples': {
                'application/json': {
                    "data": [
                        {
                            "user_real_name": "张三",
                            "approval_node": "财务审批",
                            "previous_node": "总经理审批",
                            "next_node": "董事会审批",
                            "approvers": ["张三", "李四", "王五"]
                        }
                    ],
                    "message": "审批流程信息获取成功",
                    "status": 200
                }
            }
        }
    }
})
def get_approval_process():
    """
    根据用户的实名名称和审批节点查询审批流程信息
    ---
    tags:
      - 审批流程相关接口
    """
    user_real_name = request.args.get('user_real_name')
    approval_node = request.args.get('approval_node')

    if not user_real_name or not approval_node:
        return make_response(message="缺少必要的查询参数", status=400)

    db = current_app.db

    # 查询 MongoDB 使用用户实名名称和审批节点作为条件
    query = {"user_real_name": user_real_name, "approval_node": approval_node}
    approval_data = list(db.approvals.find(query, {"_id": 0}))

    if not approval_data:
        return make_response(message="未找到匹配的审批流程信息", status=404)

    return make_response(message="审批流程信息获取成功", data=approval_data, status=200)